﻿using System;
using Crowler.Model.CoreComponents.DataAccess;
using NHibernate;
using NHibernate.Cfg;

namespace CoreComponents.DataAccess
{
    public class UnitOfWorkFactory:IUnitOfWorkFactory
    {
        private const string NhibernateConfigurationIsMissingExceptionMessage = "NHibernate configuration is missing";
        private const string YouAreNotInAUnitOfWorkExceptionMessage = "You are not in a unit of work.";
        private static ISession _currentSession;
        private static Configuration _configuration;
        private ISessionFactory _sessionFactory;


        public UnitOfWorkFactory(INHibernateConfigurationProvider configurationProvider)
        {
            _configuration = configurationProvider.CreateNHibernateConfiguration();
        }

        public IUnitOfWork Create()
        {
            var session = CreateSession();
            session.FlushMode = FlushMode.Commit;
            _currentSession = session;
            return new UnitOfWork(this, session);
        }

        private ISession CreateSession()
        {
            return SessionFactory.OpenSession();
        }

        public ISession CurrentSession
        {
            get
            {
                if (_currentSession == null)
                    throw new InvalidOperationException(YouAreNotInAUnitOfWorkExceptionMessage);
                return _currentSession;
            }
            set { _currentSession = value; }
        }

        public Configuration Configuration
        {
            get
            {
                if (_configuration == null)
                    throw new Exception(NhibernateConfigurationIsMissingExceptionMessage);
                return _configuration;
            }
            set { _configuration = value;    }
        }

        public ISessionFactory SessionFactory
        {
            get { return _sessionFactory ?? (_sessionFactory = Configuration.BuildSessionFactory()); }
        }

        public void DisposeUnitOfWork(IUnitOfWork unitOfWorkImplementor)
        {
            CurrentSession = null;
        }
    }
}
